package com.chat.websocket.util.websocket;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chat.websocket.entity.enums.GlobalConstants;
import com.chat.websocket.entity.http.Response;
import com.chat.websocket.entity.module.User;
import com.chat.websocket.entity.vo.SocketMessageVO;
import com.chat.websocket.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

@Component
@Slf4j
@ServerEndpoint(value = "/socketService/toChatWith/{userId}", encoders = {SocketEncoder.class})
public class WebSocket {

	private Session session;

	private static ApplicationContext applicationContext;

	private static final CopyOnWriteArrayList<WebSocket> WEB_SOCKETS = new CopyOnWriteArrayList<>();

	private static final Map<String, WebSocket> USERS = new HashMap<>();

	public static void setApplicationContext(ApplicationContext applicationContext) {
		WebSocket.applicationContext = applicationContext;
	}

	@OnOpen
	public void onOpen(Session session, @PathParam(value = "userId") Long userId) throws IOException {
		this.session = session;
		WEB_SOCKETS.add(this);
		UserMapper userMapper = applicationContext.getBean(UserMapper.class);
		User user = userMapper.selectById(userId);
		USERS.put(user.getUserId().toString(), this);
		log.info("连上了一个，现在总共有：{}个连接", USERS.size());
	}

	@OnClose
	public void onClose(@PathParam("userId") Long userId) {
		WEB_SOCKETS.remove(this);
		UserMapper userMapper = applicationContext.getBean(UserMapper.class);
		User user = userMapper.selectById(userId);
		USERS.remove(user.getUserId().toString());
		log.info("关闭了一个，现在总共有：{}个连接", USERS.size());
	}

	@OnMessage
	public void onMessage(String message, @PathParam(value = "userId") Long userId) throws IOException {
		UserMapper userMapper = applicationContext.getBean(UserMapper.class);
		User user = userMapper.selectById(userId);
		USERS.forEach((k, v) -> {
			if (!k.equals(user.getUserId().toString())) {
				try {
					SocketMessageVO sendMessageVO = new SocketMessageVO(user.getUserId(), user.getUserNickname(), user.getUserHeadImg(), message);
					v.session.getBasicRemote().sendObject(sendMessageVO);
				} catch (IOException | EncodeException e) {
					log.error("消息发送失败", e);
				}
			}
		});
	}

	@OnError
	public ResponseEntity<Response<String>> onError(Throwable throwable) {
		log.error("websocket通讯异常", throwable);
		return ResponseEntity.ok(Response.error(GlobalConstants.WEB_SOCKET_ERR.getCode(), GlobalConstants.WEB_SOCKET_ERR.getMessage()));
	}


	public Boolean onMessageToUser(Integer sendUserId, Integer receiveUserId, String message, Long messageId) throws IOException {
		WebSocket WebSocket = USERS.get(receiveUserId.toString());
		if (WebSocket != null && WebSocket.session.isOpen()) {
			UserMapper userMapper = applicationContext.getBean(UserMapper.class);
			User user = userMapper.selectById(sendUserId);
			SocketMessageVO sendMessageVO = new SocketMessageVO(messageId, user.getUserId(), user.getUserNickname(), user.getUserHeadImg(), message);
			try {
				WebSocket.session.getBasicRemote().sendObject(sendMessageVO);
				log.info("发送消息{}", sendMessageVO);
				return true;
			} catch (EncodeException e) {
				log.error("消息发送失败", e);
				return false;
			}
		}
		return true;
	}

	public List<User> getAllUser(Long userId) {
		List<Long> allUsers = USERS.keySet().stream().mapToLong(Long::parseLong).boxed().collect(Collectors.toList());
		allUsers.remove(userId);
		UserMapper userMapper = applicationContext.getBean(UserMapper.class);
		QueryWrapper<User> queryWrapper = new QueryWrapper();
		queryWrapper.in("user_id", allUsers);
		return userMapper.selectList(queryWrapper);
	}
}
